package br.ufpe.cin.msc.jrsj2.recommender.message;

import java.io.StringWriter;
import java.util.List;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;

import br.ufpe.cin.msc.jrsj2.recommender.persistence.domain.Profile;

public class ProfileMessage extends ApplicationMessage {

	public enum ProfileMessageAction {
		LIST_PROFILE, CREATE_PROFILE, DELETE_PROFILE
	};

	private ProfileMessageAction profileMessageAction;
	private String programTitle;
	private String clientHash;
	private float rating;

	public ProfileMessageAction getProfileMessageAction() {
		return this.profileMessageAction;
	}

	public String getProgramTitle() {
		return programTitle;
	}

	public String getClientHash() {
		return clientHash;
	}

	public float getRating() {
		return rating;
	}

	@Override
	protected void parseMessageElement(String uri, String localName,
			String qName, Attributes attributes) {
		if (qName.equals("profile")) {
			String action = attributes.getValue("action");
			if (action.equals("list")) {
				profileMessageAction = ProfileMessageAction.LIST_PROFILE;
				responseMessage = "list";
				return;
			}
			if (action.equals("create")) {
				programTitle = attributes.getValue("program");
				clientHash = attributes.getValue("client");
				rating = Float.parseFloat(attributes.getValue("rating"));
				profileMessageAction = ProfileMessageAction.CREATE_PROFILE;
				responseMessage = "create";
				return;
			}
			if (action.equals("delete")) {
				programTitle = attributes.getValue("program");
				clientHash = attributes.getValue("client");
				rating = Float.parseFloat(attributes.getValue("rating"));
				profileMessageAction = ProfileMessageAction.DELETE_PROFILE;
				responseMessage = "delete";
				return;
			}
		}
	}

	@SuppressWarnings("rawtypes")
	@Override
	public void buildResponseMessage(List objects) {
		DocumentBuilderFactory docFactory = DocumentBuilderFactory
				.newInstance();
		Document document;
		Node root;

		try {
			document = docFactory.newDocumentBuilder().newDocument();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			return;
		}
		root = document.createElement("profile-list");
		document.appendChild(root);

		@SuppressWarnings("unchecked")
		List<Profile> profiles = objects;

		for (Profile p : profiles) {
			Element profile = document.createElementNS(null, "profile");
			if (p.getProgram() != null)
				profile.setAttributeNS(null, "program", p.getProgram()
						.getTitle());
			else
				profile.setAttributeNS(null, "program", "null");
			if (p.getClient() != null)
				profile.setAttributeNS(null, "client", p.getClient().getHash());
			else
				profile.setAttributeNS(null, "client", "null");
			profile.setAttributeNS(null, "rating",
					String.valueOf(p.getRating()));
			root.appendChild(profile);
		}

		TransformerFactory transformerFactory = TransformerFactory
				.newInstance();
		StringWriter writer = new StringWriter();
		try {
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(document);
			StreamResult result = new StreamResult(writer);
			transformer.transform(source, result);
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}

		ApplicationMessage.responseMessage = writer.toString();
	}

	@Override
	protected void parseMessageContent(char[] ch, int start, int length) {
	}

	@Override
	protected void parseMessageEndElement(String uri, String localName,
			String qName) {
	}

}
